/*
 * MIT License
 *
 * Copyright (c) 2025 Mark·虎
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

package com.hsxxherp.key.uia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hsxxherp.key.uia.entity.SysApplicationVersion;
import com.hsxxherp.key.uia.entity.SysApplicationVersion.DeployStatus;
import com.hsxxherp.key.uia.entity.SysApplicationVersion.VersionStatus;
import com.hsxxherp.key.uia.mapper.SysApplicationVersionMapper;
import com.hsxxherp.key.uia.service.ISysApplicationVersionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.OffsetDateTime;
import java.util.List;

/**
 * 应用版本服务实现类
 * 继承自 ServiceImpl 类，实现 ISysApplicationVersionService 接口
 *
 * @author Mark·虎（2486970363@qq.com）
 */
@Service
public class SysApplicationVersionServiceImpl extends ServiceImpl<SysApplicationVersionMapper, SysApplicationVersion> implements ISysApplicationVersionService {

    private static final Logger logger = LoggerFactory.getLogger(SysApplicationVersionServiceImpl.class);

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysApplicationVersion createVersion(SysApplicationVersion version) {
        if (version.getVersionNum() == null || version.getVersionNum().isEmpty()) {
            logger.error("创建版本时版本号为空");
            throw new RuntimeException("版本号不能为空");
        }
        QueryWrapper<SysApplicationVersion> versionQueryWrapper = new QueryWrapper<>();
        versionQueryWrapper.eq("version_num", version.getVersionNum())
                .eq("app_id", version.getAppId());
        if (count(versionQueryWrapper) > 0) {
            logger.error("应用 {} 已存在版本号为 {} 的记录，无法创建", version.getAppId(), version.getVersionNum());
            throw new RuntimeException("该应用已存在相同版本号的记录，无法添加");
        }
        version.setReleaseTime(OffsetDateTime.now());
        version.setStatus(VersionStatus.CREATED);
        version.setDeployStatus(DeployStatus.NOT_DEPLOYED);
        boolean success = super.save(version);
        if (success) {
            logger.info("成功创建应用版本，版本 ID: {}", version.getVersionId());
            return version;
        }
        logger.error("创建应用版本失败，版本信息: {}", version);
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysApplicationVersion updateVersion(SysApplicationVersion version) {
        SysApplicationVersion existingVersion = getById(version.getVersionId());
        if (existingVersion == null) {
            logger.error("要更新的应用版本不存在，版本 ID: {}", version.getVersionId());
            throw new RuntimeException("要更新的应用版本不存在");
        }
        if (version.getVersionNum() == null || version.getVersionNum().isEmpty()) {
            logger.error("更新版本时版本号为空，版本 ID: {}", version.getVersionId());
            throw new RuntimeException("版本号不能为空");
        }
        QueryWrapper<SysApplicationVersion> versionQueryWrapper = new QueryWrapper<>();
        versionQueryWrapper.eq("version_num", version.getVersionNum())
                .eq("app_id", version.getAppId())
                .ne("version_id", version.getVersionId());
        if (count(versionQueryWrapper) > 0) {
            logger.error("应用 {} 已存在版本号为 {} 的记录，无法更新版本 ID 为 {} 的记录", version.getAppId(), version.getVersionNum(), version.getVersionId());
            throw new RuntimeException("该应用已存在相同版本号的记录，无法修改");
        }
        version.setReleaseTime(OffsetDateTime.now());
        boolean success = updateById(version);
        if (success) {
            logger.info("成功更新应用版本，版本 ID: {}", version.getVersionId());
            return getById(version.getVersionId());
        }
        logger.error("更新应用版本失败，版本 ID: {}", version.getVersionId());
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteVersion(String versionId) {
        SysApplicationVersion existingVersion = getById(versionId);
        if (existingVersion == null) {
            logger.error("要删除的应用版本不存在，版本 ID: {}", versionId);
            throw new RuntimeException("要删除的应用版本不存在");
        }
        boolean success = removeById(versionId);
        if (success) {
            logger.info("成功删除应用版本，版本 ID: {}", versionId);
        } else {
            logger.error("删除应用版本失败，版本 ID: {}", versionId);
        }
        return success;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysApplicationVersion publishVersion(String versionId) {
        SysApplicationVersion version = getById(versionId);
        if (version == null) {
            logger.error("要发布的应用版本不存在，版本 ID: {}", versionId);
            throw new RuntimeException("要发布的应用版本不存在");
        }
        if (!DeployStatus.DEPLOYED.equals(version.getDeployStatus())) {
            logger.error("版本 ID 为 {} 的应用版本部署状态为 {}，不能发布", versionId, version.getDeployStatus().getDescription());
            throw new RuntimeException("只有已部署的版本才能发布");
        }
        version.setStatus(VersionStatus.PUBLISHED);
        version.setReleaseTime(OffsetDateTime.now());
        boolean success = updateById(version);
        if (success) {
            logger.info("成功发布应用版本，版本 ID: {}", versionId);
            return getById(versionId);
        }
        logger.error("发布应用版本失败，版本 ID: {}", versionId);
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysApplicationVersion rollbackVersion(String versionId) {
        SysApplicationVersion version = getById(versionId);
        if (version == null) {
            logger.error("要回滚的应用版本不存在，版本 ID: {}", versionId);
            throw new RuntimeException("要回滚的应用版本不存在");
        }
        if (!VersionStatus.PUBLISHED.equals(version.getStatus())) {
            logger.error("版本 ID 为 {} 的应用版本状态为 {}，不能回滚", versionId, version.getStatus().getDescription());
            throw new RuntimeException("只有已发布的版本才能回滚");
        }
        String prevVersionId = version.getPrevVersionId();
        if (prevVersionId == null) {
            logger.error("版本 ID 为 {} 的应用版本没有前一个版本，无法回滚", versionId);
            throw new RuntimeException("该版本没有前一个版本，无法回滚");
        }
        SysApplicationVersion prevVersion = getById(prevVersionId);
        if (prevVersion == null) {
            logger.error("版本 ID 为 {} 的应用版本的前一个版本不存在，无法回滚", versionId);
            throw new RuntimeException("前一个版本不存在，无法回滚");
        }
        version.setStatus(VersionStatus.ROLLED_BACK);
        updateById(version);
        prevVersion.setStatus(VersionStatus.PUBLISHED);
        prevVersion.setReleaseTime(OffsetDateTime.now());
        updateById(prevVersion);
        logger.info("成功回滚应用版本，当前版本 ID: {}，回滚到版本 ID: {}", versionId, prevVersionId);
        return prevVersion;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysApplicationVersion startTesting(String versionId) {
        SysApplicationVersion version = getById(versionId);
        if (version == null) {
            logger.error("要开始测试的应用版本不存在，版本 ID: {}", versionId);
            throw new RuntimeException("要开始测试的应用版本不存在");
        }
        if (!VersionStatus.CREATED.equals(version.getStatus())) {
            logger.error("版本 ID 为 {} 的应用版本状态为 {}，不能开始测试", versionId, version.getStatus().getDescription());
            throw new RuntimeException("只有已创建的版本才能开始测试");
        }
        version.setStatus(VersionStatus.TESTING);
        boolean success = updateById(version);
        if (success) {
            logger.info("成功开始应用版本测试，版本 ID: {}", versionId);
            return getById(versionId);
        }
        logger.error("开始应用版本测试失败，版本 ID: {}", versionId);
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysApplicationVersion startDeployment(String versionId) {
        SysApplicationVersion version = getById(versionId);
        if (version == null) {
            logger.error("要开始部署的应用版本不存在，版本 ID: {}", versionId);
            throw new RuntimeException("要开始部署的应用版本不存在");
        }
        if (!VersionStatus.TESTING.equals(version.getStatus()) && !VersionStatus.ROLLED_BACK.equals(version.getStatus())) {
            logger.error("版本 ID 为 {} 的应用版本状态为 {}，不能开始部署", versionId, version.getStatus().getDescription());
            throw new RuntimeException("只有测试中或已回滚的版本才能开始部署");
        }
        if (!DeployStatus.NOT_DEPLOYED.equals(version.getDeployStatus())) {
            logger.error("版本 ID 为 {} 的应用版本部署状态为 {}，不能开始部署", versionId, version.getDeployStatus().getDescription());
            throw new RuntimeException("只有未部署的版本才能开始部署");
        }
        version.setDeployStatus(DeployStatus.DEPLOYING);
        boolean success = updateById(version);
        if (success) {
            logger.info("成功开始应用版本部署，版本 ID: {}", versionId);
            return getById(versionId);
        }
        logger.error("开始应用版本部署失败，版本 ID: {}", versionId);
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysApplicationVersion markDeploymentSuccess(String versionId) {
        SysApplicationVersion version = getById(versionId);
        if (version == null) {
            logger.error("要标记部署成功的应用版本不存在，版本 ID: {}", versionId);
            throw new RuntimeException("要标记部署成功的应用版本不存在");
        }
        if (!DeployStatus.DEPLOYING.equals(version.getDeployStatus())) {
            logger.error("版本 ID 为 {} 的应用版本部署状态为 {}，不能标记部署成功", versionId, version.getDeployStatus().getDescription());
            throw new RuntimeException("只有部署中的版本才能标记部署成功");
        }
        version.setDeployStatus(DeployStatus.DEPLOYED);
        boolean success = updateById(version);
        if (success) {
            logger.info("成功标记应用版本部署成功，版本 ID: {}", versionId);
            return getById(versionId);
        }
        logger.error("标记应用版本部署成功失败，版本 ID: {}", versionId);
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysApplicationVersion markDeploymentFailed(String versionId) {
        SysApplicationVersion version = getById(versionId);
        if (version == null) {
            logger.error("要标记部署失败的应用版本不存在，版本 ID: {}", versionId);
            throw new RuntimeException("要标记部署失败的应用版本不存在");
        }
        if (!DeployStatus.DEPLOYING.equals(version.getDeployStatus())) {
            logger.error("版本 ID 为 {} 的应用版本部署状态为 {}，不能标记部署失败", versionId, version.getDeployStatus().getDescription());
            throw new RuntimeException("只有部署中的版本才能标记部署失败");
        }
        version.setDeployStatus(DeployStatus.DEPLOY_FAILED);
        boolean success = updateById(version);
        if (success) {
            logger.info("成功标记应用版本部署失败，版本 ID: {}", versionId);
            return getById(versionId);
        }
        logger.error("标记应用版本部署失败失败，版本 ID: {}", versionId);
        return null;
    }

    @Override
    public List<SysApplicationVersion> getPublishedVersionsByAppId(String appId) {
        QueryWrapper<SysApplicationVersion> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("app_id", appId)
                .eq("status", VersionStatus.PUBLISHED.getCode());
        return list(queryWrapper);
    }
}